/* 
 * File:   methods.cpp
 * Author: root
 * 
 * Created on 21 mai 2009, 13:46
 */

#include "methods.h"

Methods::Methods() {
}

Methods::Methods(const Methods& orig) {
}

Methods::Methods(char * filename){

    strcpy(imageFile,filename);
    verbose=false;
    seuil1=25;
    seuil2=45;
    backpix=0;
}

Methods::~Methods() {
}


//******************************************************************************
//  Fonction : setParam(): Initialise les parametres globaux
//******************************************************************************

void Methods::setParam(int iheight,int iwidth){

    	height = iheight;
	width = iwidth;
}

void Methods::setBack(int ibackpix){
        backpix =ibackpix;
}


//******************************************************************************
//              FONCTIONS AUXILIAIRES DU PROGRAMME
//
//******************************************************************************




//******************************************************************************
//  Fonction : arrayToMatrix(): Convertit un vecteur 1D en une matrice 2D
//  Input    : Le vecteur 1D : array
//             La taille de la matrice : width, height
//  Output   : La matrice 2D :  matrix
//******************************************************************************

float **Methods::arrayToMatrix(float *array) {
	float **matrix = (float **)malloc(height * sizeof(float *));
	for (int i = 0; i < height; i ++)
		matrix[i] = (float *)malloc(width * sizeof(float));

	for (int i = 0; i < height; i ++)
		for (int j = 0; j < width; j ++)
			matrix[i][j] = array[i * width + j];
	return matrix;
}

//******************************************************************************
//  Fonction : arrayToImage(): Convertit un vecteur 1D en une image
//  Input    : Le vecteur 1D : array
//  Output   : L'image :  image
//******************************************************************************

Image* Methods::arrayToImage(float *array) {
	float max = 0;
	for (int i = 0; i < height * width; i ++)
		if (max < array[i]) max = array[i];
	ImageGray *image = new ImageGray(width, height);
	image->copyFrom(width, height, array, "gray", max);
	return image;
}


//******************************************************************************
//  Fonction : loadImage(): Construit une image à partir d'un fichier
//  Input    : Le nom du fichier  : fileName
//  Output   : L'image :  image
//******************************************************************************

ImageRgb* Methods::loadImage(char *fileName) {
	ImageRgb *image = NULL;
	jpegDiskXFile *imageFile = NULL;

	imageFile = new jpegDiskXFile(fileName, "r");
	image = new ImageRgb();
	if(!image->loadImageXFile(imageFile))
		error("Impossible to load the image");
        setParam(image->height,image->width);

	delete imageFile;
	return image;
}

//******************************************************************************
//  Fonction : getGrayValue(): Calcule la valeur en niveau de gris d'un pixel
//  Input    : Une chaine contenant les composantes du pixel: pixel
//  Output   : L'intensité du pixel en niveau de gris : grayValue
//******************************************************************************

float Methods::getGrayValue(unsigned char *pixel)
{
	float grayValue = 0;
	for (int i = 0; i < 3; i ++)
		grayValue += pixel[i];
	grayValue /= 3;
	return grayValue;
}


//******************************************************************************
//  Fonction : imageToMatrix(): Convertit une image couleur en une matrice
//             correspondant aux pixel en niveau de gris de l'image
//  Input    : L'image couleur RGB
//  Output   : La matrice 2D :  matrix
//******************************************************************************

float **Methods::imageToMatrix(ImageRgb *image) {

	//Initialiser la matrice
	float **matrix = (float **)malloc(height * sizeof(float *));
	for (int i = 0; i < image->height; i ++)
		matrix[i] = (float *)malloc(width * sizeof(float));

	//Calculer les valeurs
		for (int i = 0; i < height; i ++)
			for (int j = 0; j < width; j ++)
				matrix[i][j] = getGrayValue(image->get(i, j));
	return matrix;
}

//******************************************************************************
//  Fonction : matrixToImage(): Convertit une matrice 2D en une image grise
//  Input    : La matrice 2D :  matrix
//  Output   : L'image grise : image
//******************************************************************************

ImageGray *Methods::matrixToImage(float **matrix) {
	ImageGray *image = new ImageGray(width, height);
	for (int i = 0; i < height; i ++)
		for (int j = 0; j < width; j ++)
			image->get(i, j)[0] = matrix[i][j];
	image->updateDataFromPixmap();
	return image;
}


//******************************************************************************
//  Fonction : getMean(): Calcule la valeur des pixels au voisinage de (x,y)
//  Input    : La matrice 2D qui représente l'image:  matrix
//             Les cordonnées x,y du pixel central
//  Output   : La moyenne des pixels
//******************************************************************************


float Methods::getMean(float **matrix, int x, int y) {
	float mean = 0;
	for (int i = y - 1; i <= y + 1; i ++)
		for (int j = x - 1; j <= x + 1; j ++)
			mean += matrix[i][j];
	mean /= 9;
	return mean;
}


//******************************************************************************
//  Fonction : meanFilter(): Applique le filtre moyen à une image
//  Input    : La matrice 2D qui représente l'image:  matrix
//  Output   : L'image filtrée: matrix
//******************************************************************************

void Methods::meanFilter(float **matrix) {
	float **temp = (float **)malloc(height * sizeof(float *));
	for (int i = 0; i < height; i ++)
		temp[i] = (float *)malloc(width * sizeof(float));

	for (int i = 1; i < height - 1; i ++)
		for (int j = 1; j < width -1; j ++)
			temp[i][j] = getMean(matrix, j, i);
	for (int i = 1; i < height - 1; i ++)
		for (int j = 1; j < width -1; j ++)
			matrix[i][j] = temp[i][j];
}

//******************************************************************************
//  Fonction : calculateGradient(): Applique le filtre de Canny pour deterniner
//             les contours
//  Input    : L'image en niveau de gris:  image
//  Output   : Le verteur gradient contenant les contours de l'image
//******************************************************************************

float *Methods::calculateGradient(Image *image)
{
        float threshold=10;
	ipCore *gradientHolder = NULL;
	gradientHolder = new ipCanny(image->width, image->height, "gray", threshold);
	gradientHolder->process(image);
	return gradientHolder->seq_out->frames[2];
	
}

//******************************************************************************
//  Fonction : getBackColor(): Determine la valeur du pixel du fond de l'image
//            hypothèse: c'est le pixel majoritaire dans l'histogramme.
//  Input    : L'image en niveau de gris:  origine
//  Output   : La valeur du pixel de fond : back
//******************************************************************************

int Methods::getBackColor(Image *origine)
{
    int back=0;

    ipCore *histo = NULL;

    histo = new ipHisto(origine->width, origine->height, "gray");
    histo->setBOption("normalise", false);
    histo->process(origine);

    real *h = histo->seq_out->frames[0];

    real max = 1.0;

    for(int i=0; i<256; i++)
	if (max < h[i]) {
            max = h[i];
            back = i;
	}
    return back;
}

//******************************************************************************
//  Fonction : thresholdBinary(): Binairise une image suivant un certain seuil
//  Input    : La matrice 2D qui représente l'image:  matrix
//             Le seuil
//  Output   : L'image binairisée
//******************************************************************************

void Methods::thresholdBinary(float **matrix, int threshold)
{
	for (int i = 0; i < height; i ++)
		for (int j = 0; j < width; j ++)
		{
			if (matrix[i][j] < threshold) matrix[i][j] = 0;
			else matrix[i][j] = 255;
		}
}


//******************************************************************************
//  Fonction : erosion(): Effectue l'érosion de l'image
//             Version disponible dans Torch3 Vision
//  Input    : La matrice 2D qui représente l'image:  matrix
//  Output   : L'image après erosion
//******************************************************************************

void Methods::erosion(float **matrix)
{
  int iteration=1;
  int radius=10;
  int threshold=100;

  Image *image_in = NULL;
  image_in = matrixToImage(matrix);

  ipCore *morph = NULL;
  morph = new ipErode(image_in->width, image_in->height, "gray", iteration, radius, threshold);
  morph->setBOption("verbose", verbose);
  morph->process(image_in);

  matrix = arrayToMatrix(morph->seq_out->frames[0]);

  delete morph;
  delete image_in;

}

//******************************************************************************
//  Fonction : dilatation(): Effectue la dilatation de l'image
//             Version disponible dans Torch3 Vision
//  Input    : La matrice 2D qui représente l'image:  matrix
//  Output   : L'image après dilatation
//******************************************************************************

void Methods::dilatation(float **matrix)
{

  int iteration=1;
  int radius=1;
  int threshold=100;
  bool xy=false;
  
  Image *image_in = NULL;
  image_in = matrixToImage(matrix);

 ipCore *morph = NULL;

if(xy)
    morph = new ipDilateXY(image_in->width, image_in->height, "gray", iteration, radius, radius, threshold);
else
    morph = new ipDilate(image_in->width, image_in->height, "gray", iteration, radius, threshold);

  morph->setBOption("verbose", verbose);
  morph->process(image_in);
  
  matrix = arrayToMatrix(morph->seq_out->frames[0]);
  
  delete morph;
  delete image_in;
}

//******************************************************************************
//  Fonction : applyMask(): Effectue la fusion du masque et de l'image d'origine
//
//  Input    : La matrice contenant le masque à appliquer: matrix
//             L'image d'origine en couleur RGB
//             Le nom du fichier résultat
//  Output   : L'image résultat de la segmentation par le masque.
//******************************************************************************

void Methods::applyMask(float **matrix,ImageRgb *imageIn, char *name)
{
  ImageRgb *imageOut;
  imageOut = new ImageRgb();
  imageOut->copyFrom(imageIn);
  for (int i = 0; i < height; i ++)
    for (int j = 0; j < width; j ++)
       	if (matrix[i][j] == 0)
              	for (int color = 0; color < 3; color ++)
			imageOut->get(i, j)[color] = 0;
  imageOut->save(name);

delete imageOut;
}


//******************************************************************************
//  Fonction : getName(): Fonction de nommage des fichiers résultats
//******************************************************************************


char*  Methods::getName(int pos) {

        char *title= new char[300];
        char *name= new char[300];


        switch ( pos ) {

            case 0 :
                        strcpy(title,"_Gray");
                        strcpy(name, setTitle(imageFile,title));
                        strcat(name, (char*)".pgm");
                     break;

            case 1 :
                        strcpy(title,"_Binary");
                        strcpy(name, setTitle(imageFile,title));
                        strcat(name, (char*)".pgm");
                     break;
            case 2 :
                        strcpy(title,"_Dila&Ero");
                        strcpy(name, setTitle(imageFile,title));
                        strcat(name, (char*)".pgm");
                     break;

            case 3 :
                        strcpy(title,"_Canny");
                        strcpy(name, setTitle(imageFile,title));
                        strcat(name, (char*)".ppm");
                     break;
            case 4 :
                        strcpy(title,"_Contours");
                        strcpy(name, setTitle(imageFile,title));
                        strcat(name, (char*)".ppm");
                     break;
            case 5 :
                        strcpy(title,"_Mask");
                        strcpy(name, setTitle(imageFile,title));
                        strcat(name, (char*)".ppm");
                     break;
            case 6 :
                        strcpy(title,"_Final");
                        strcpy(name, setTitle(imageFile,title));
                        strcat(name, (char*)".ppm");
                     break;

            default :
                        strcpy(title,"_default");
                        strcpy(name, setTitle(imageFile,title));
                        strcat(name, (char*)".ppm");
                     break;
    }

return  name;
}

//******************************************************************************
//  Fonction : setTitle(): Utilisé pour le nommage des fichiers résultats
//******************************************************************************

char *  Methods::setTitle(char* string,char* prefix)
{

	char *str = new char[300];
	char *str1 = new char[300];
	int i, j=0;

// Extraction du nom du fichier sans extension

	for (i = 0; string[i] != '\0'; i ++)
	 {
           if(string[i]!='/')
            {
  	     str[j] = string[i];
             j++;
            }
	   else
            {
	    j=0;
             }
         }
	str[j ++] = (char)NULL;

	for (i = 0; str[i] != '.'; i ++)
	 {
          str1[i] = str[i];
         }

        str1[i] = (char)NULL;

	strcat(str1, prefix);
	return str1;
}

//******************************************************************************
//  Fonction : firstTraitment(): Effectue une première segmentation de l'image
//             En mettant tous les pixels de couleur proche de celle du fond
//             à 0.
//  Input    : La matrice 2D qui représente l'image:  matrix
//  Output   : La matrice 2D qui représente l'image segmenté en deux zones
//             le fond de l'image et l'ensemble des objets de l'image
//******************************************************************************

float ** Methods::firstTraitment(float **matrix)
{
  Image *image_in = NULL;
  ImageRgb *image_out = NULL;
  image_in = matrixToImage(matrix);
  image_out = new ImageRgb(width,height);

  for(int x=0; x<image_in->height; x++)
        for(int y=0; y<image_in->width; y++) {
            
                if ((image_in->get(x, y)[0] <= (backpix + seuil1)) && (image_in->get(x, y)[0] >= (backpix - seuil2))) {
                        for (int i=0; i<3; i++) {
                                image_out->get(x, y)[i] = 0;
                        }
                } else {
                        for (int i=0; i<3; i++) {
                                image_out->get(x, y)[i] = 255;
                        }
                }
        }  

  matrix = imageToMatrix(image_out);
  delete image_in;
  delete image_out;

  return matrix;
}


//******************************************************************************
//  Fonction : localSegment(): Effectue la segmentation d'un seul objet de l'image
//             En construisant un masque avec tous les autres pixels à 0
//  Input    : La matrice 2D qui représente le masque général:  matrix
//           : L'image couleur d'origine: imageIn
//           : L'étiquette de la région à segmenter
//  Output   : L'image correspondante au masque de segmentation de cet objet:
//             L'image résultante de la segmentation qui est une fusion de ce
//             masque et de l'image d'origine
//******************************************************************************

void Methods::localSegment(float **matrix, int **Labels, int label, ImageRgb *imageIn,int id)
{

  Image *imageOut = NULL;

  for(int x=0; x<height; x++)
      for(int y=0; y<width; y++) 
            if(Labels[x][y]==label)
               matrix[x][y]=255;
            else
               matrix[x][y]=0;
           
 char *name= new char[300];
 char *title= new char[300];
 char *name1= new char[300];
 char *thresh= new char[300];
 sprintf (thresh, "%d", id);
 strcpy(title,"_Region-");
 strcpy(name, setTitle(imageFile,title));
 strcat(name, thresh);
 strcpy(name1, name);
 strcat(name, (char*)".ppm");
 strcat(name1, (char*)"-Mask.ppm");

imageOut = matrixToImage(matrix);
imageOut->save(name1);
print("     8.%d   - Masque de l'objet ->         %s  :OK\n",id,name1);
applyMask(matrix,imageIn,name);
print("           - Segmentation de l'objet ->   %s       :OK\n\n",name);

delete imageOut;
}


//******************************************************************************
//  Fonction : labelRegion(): Effectue l'étiquetage de tous les pixels de l'image
//             En faisant des parcours de l'image haut-bas et bas-haut
//  Input    : La matrice 2D qui représente le masque général de l'image:  matrix
//  Output   : La matrice contenant les étiquettes de tous les pixels: Labels
//             Le numero de la plus grande étiquette: nb
//******************************************************************************

int ** Methods::labelRegion(float **matrix,int *nb)
{

    int label = 0;
    int lab;
    // Initialisation de la matrice des étiquettes

    int **Labels = (int **)malloc(height * sizeof(int *));
    for (int i = 0; i < height; i ++)
            Labels[i] = (int *)malloc(width * sizeof(int));
    for (int x=0; x<height; x++) {
       for (int y=0; y<width; y++) {
             Labels[x][y] = 0;
            }
    }
    // Premier parcours de l'image du haut vers le bas

    for(int x=1; x<height-1; x++)
            for(int y=1; y<width-1; y++) {
                    if (matrix[x][y] != 0)
                      {  
                            if (newkLabel(Labels,x, y)) {
                                    label++;
                                    Labels[x][y] = label;
                            } else
                                {
                                     if(changeLabel(Labels,x, y,&lab))
                                     {
                                      Labels[x][y] = lab;
                                    }

                                }
                    }
            }

    // Deuxième parcours de l'image du bas vers le haut
    bool loop;
    do {
    loop=false;
    for(int x=height-1; x>=0; x--)
            for(int y=width-1; y>=0; y--) 
                    if (matrix[x][y] != 0)
                         if(changeLabel(Labels,x, y,&lab)) {
                              Labels[x][y] = lab;
                              loop=true;
                            }
    // Reprendre le processus jusqu'a ce que rien ne bouge
    //    Du haut vers le bas
    if(loop){

        for(int x=1; x<height-1; x++)
                     for(int y=1; y<width-1; y++)
                            if (matrix[x][y] != 0)
                                 if(changeLabel(Labels,x, y,&lab)) {
                                      Labels[x][y] = lab;
                                      loop=true;
                                    }

      }
      }while(loop);

    *nb=label;
 
  return Labels;
}


//******************************************************************************
//  Fonction : getNumLabels(): Range toutes les étiquettes des objets dans
//             un tableau, en éliminant les étiquettes vides (qui n'ont aucun pixel)
//  Input    : La matrice contenant les étiquettes de tous les pixels: Labels
//           : Le numero de l'étiquette la plus grande
//  Output   : Un tableau contenant les étiquettes non vides
//             Le nombre d'étiquette non vides (taille du tableau)
//******************************************************************************

int *Methods::getNumLabels(int **Labels, int label,int *labelout)
{
int *numLabel= new int[100];
int k=0;
for(int i=0;i<label;i++)
     if(emptyLabel(Labels,i))
     { numLabel[k]=i;
        k++;
     }
*labelout=k;
return numLabel;
}

//******************************************************************************
//  Fonction : newkLabel(): Vérifie si il faut ajouter un nouvel étiquette pour
//             pour un pixel en (x,y): utilisée par la fonction labelRegion
//******************************************************************************

bool Methods::newkLabel(int **Labels, int x, int y)
{
        
    return (Labels[x-1][y-1] == 0) && (Labels[x-1][y] == 0) && (Labels[x-1][y+1] == 0) && (Labels[x][y-1] == 0);
}

//******************************************************************************
//  Fonction : changeLabel(): Vérifie si la valeur de l'étiquette du pixel en (x,y)
//             doit être modifiée: utilisée par la fonction labelRegion
//  Input    : La matrice contenant les étiquettes de tous les pixels: Labels
//             Les coordonnées (x,y) du pixel
//  Output   : Un booléan indiquant si oui ou non la valeur doit changer
//             La valeur de la nouvelle étiquete pour ce pixel
//******************************************************************************

bool Methods::changeLabel(int **Labels, int x, int y, int *lab)
{
    *lab =100;
  for(int ix=x-1; ix<x+2; ix++)  // recherche du plus petit voisin
    for(int iy=y-1; iy<y+2; iy++)
       { 
            if ((Labels[ix][iy] > 0)&&(Labels[ix][iy] < *lab))
                 *lab= Labels[ix][iy];
       }

  if(*lab!=Labels[x][y])
    return true;
  
  return false;
}

//******************************************************************************
//  Fonction : emptyLabel(): Vérifie si une étiquette est vide ou non 
//             utilisée par la fonction getNumLabels
//******************************************************************************

bool Methods::emptyLabel(int **Labels,int lab)
{
    for(int x=0; x<height; x++)
       for(int y=0; y<width; y++)
          if(lab==Labels[x][y])
           return true;
 
  return false;
}


//******************************************************************************
//  Fonction : setConnect(): Utilise la connexité 8 pour affecter la même couleur
//             aux pixels voisons de (x,y): utilsé par le fonction traceContours
//  Input    : La matrice 2D qui représente l'image:  matrix
//             Les coordonnées (x,y) du pixel
//******************************************************************************

void Methods::setConnect(float **matrix, int x, int y)
{
	for (int i = y - 1; i <= y + 1; i ++)
		for (int j = x - 1; j <= x + 1; j ++)
			if (matrix[i][j] == 255)
			{
				matrix[i][j] = matrix[y][x];
				setConnect(matrix, j, i);
			}
}

//******************************************************************************
//  Fonction : traceContours(): Determine les contours des objets de l'image
//  Input    : La matrice 2D qui représente l'image dilatation et erosion:  matrix
//  Output   : La matrice 2D qui représente l'image avec les contours des objets:  matrix
//             le nombre de segment ou d'objets dans l'image: nSegment
//******************************************************************************

int Methods::traceContours(float **matrix)
{
	int nSegment = 0;
	for (int i = 0; i < height; i ++)
		for (int j = 0; j < width; j ++)
			if (matrix[i][j] == 255)
			{
				nSegment ++;
				matrix[i][j] = nSegment;
				setConnect(matrix, j, i);
			}
	return nSegment;
}


//******************************************************************************
//  Fonction : fillSegments(): Remplit les segment identifiés par les contours
//             des objets.
//  Input    : La matrice 2D qui représente l'image après traçage des contours:  matrix
//  Output   : La matrice 2D qui représente le masque générale de l'image:  matrix
//******************************************************************************


void Methods::fillSegments(float **matrix)
{
	int segment; //la couleur de segment aussi
	int p;

	for (int i = 0; i < height; i ++)
		for (int j = 0; j < width; j ++)
		{
			if (matrix[i][j] != 0)
			{
				segment = matrix[i][j];
                                int j1=j;
				while (j1 < width && matrix[i][j1] == segment) j1 ++;
				p = j1;
				while (j1 < width && matrix[i][j1] != segment) j1 ++;
				if (j1 < width)
				{
					for (int k = p; k < j1; k ++)
						matrix[i][k] = segment;
				}
				while (j1 < width &&matrix[i][j1] == segment) j1 ++;
			}
		}

        for (int j = 0; j < width; j ++)
                for (int i = 0; i < height; i ++)
		{
			if (matrix[i][j] != 0)
			{
				segment = matrix[i][j];
                                int i1=i;
				while (i1 < height && matrix[i1][j] == segment) i1 ++;
				p = i1;
				while (i1 < height && matrix[i1][j] != segment) i1 ++;
				if (i1 < height)
				{
					for (int k = p; k < i1; k ++)
						matrix[k][j] = segment;
				}
				while (i1 < height &&matrix[i1][j] == segment) i1 ++;
			}
		}
}


//******************************************************************************
//  Fonction : secondTraitment(): Effectue une série de dilatation et d'erosion, ensuite
//             applique un filtrage par moyenne et un filtrage gradient de l'image
//  Input    : La matrice contenant l'image binaire après la première segmentation: matrix
//  Output   : L'image résultat de la segmentation par le masque.
//******************************************************************************

float * Methods::secondTraitment(float **matrix){

   Image *imageOut1 = NULL;
   Image *imageOut = NULL;

   float * gradientVector;

    for (int i = 0; i < 2; i ++)
    {
        meanFilter(matrix);
    }
        for (int i = 0; i < 5; i ++)
              dilatation(matrix);

         for (int i = 0; i < 5; i ++)
              erosion(matrix);

	imageOut = matrixToImage(matrix);
        thresholdBinary(matrix,1);
        imageOut1 = matrixToImage(matrix);
	imageOut1->save(getName(2));

print("  3. Filtre Moyen +Dilatation + Erosion -> %s  :OK\n",getName(2));

	/* Calculer le gradient deuxieme fois
	 * On va avoir deux contours (contours de contour) de même objet
	 * On va utiliser le contour extérieur pour assurer que il va contenir tout l'objet
	 */
	gradientVector = calculateGradient(imageOut1);
	imageOut1 = arrayToImage(gradientVector);
	imageOut1->save(getName(3));

print("  4. Filtre Canny -> %s  :OK\n",getName(3));

        delete imageOut;
        delete imageOut1;

        return gradientVector;
}

//******************************************************************************
//  Fonction : thirdTraitment(): Elle termine la phase de prétraitement
//             Elle  detecte les contours des objets et les remplit par la suite
//  Input    : La matrice contenant l'image après prétraitement(Binaire + Erosion et dilatation): matrix
//  Output   : L'image du masque globle de l'image 
//******************************************************************************


float ** Methods::thirdTraitment(float **matrix)
{

    Image *imageOut = NULL;
//Tracer les contours
    traceContours(matrix);
    imageOut = matrixToImage(matrix);
    imageOut->save(getName(4));
    delete imageOut;

print("  5. Detection des contours -> %s  :OK\n",getName(4));
    //Remplir les segments
    fillSegments(matrix);
    thresholdBinary(matrix,1);

    for (int i = 0; i < 5; i ++)
     erosion(matrix);

    imageOut = matrixToImage(matrix);
    imageOut->save(getName(5));

print("  6. Remplissage des vides -> %s  :OK\n",getName(5));

    return matrix;
}

//******************************************************************************
//  Fonction : finalSegment(): C'est la procédure principale du programme
//             Elle combine toutes les autres pour éffectue d'abord la segmentation
//             globale de l'image et ensuite celle de tous les objets
//  Input    : La matrice contenant l'image après prétraitement(Binaire + Erosion et dilatation): matrix
//             L'image d'origine en couleur RGB
//  Output   : L'image du masque globle de l'image et l'image segmentée
//             L'image du masque local à chaque objet et l'image de la segmentation de l'objet.
//******************************************************************************

void Methods::finalSegment(float **matrix,ImageRgb *imageIn ) {

    Image *imageOut = NULL;

//Associer avec l'image origine pour afficher le résultat

    applyMask(matrix,imageIn,getName(6));

print("  7. Segmentation globale -> %s  :OK\n",getName(6));

    int nb,nbout;
    int** Labels=labelRegion(matrix,&nb);
    int *numLabel=getNumLabels(Labels,nb,&nbout);

// Dessiner toutes les régions de l'image

print("  8. Segmentation par objet :  %d  Objets\n\n",nbout-1);

    for(int i=1;i<nbout;i++) // indice O c'est le fond de l'image
    {
      localSegment(matrix,Labels,numLabel[i], imageIn,i);
    }

delete imageOut;
}